package org.zoomdev.zoom.rpc.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.zoomdev.zoom.aop.Interceptor;
import org.zoomdev.zoom.serializer.SerializerFactory;

/**
 * n个工作线程
 * 1个写线程
 * 1个读线程
 */
public final class RpcServer {
    private static final Log log = LogFactory.getLog(RpcServer.class);
    private final ServiceContainer serviceContainer;
    private int port;
    private int threadCount = Runtime.getRuntime().availableProcessors() * 2;

    public RpcServer(SerializerFactory serializerFactory) {
        serviceContainer = new ServiceContainer(serializerFactory);
    }


    public void setInterceptor(Interceptor interceptor) {
        serviceContainer.setInterceptor(interceptor);
    }

    public void join() {
        try {
            bootstrapFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {

        }
    }

    public void setThreadCount(int count) {
        if (count <= 0) {
            throw new IllegalArgumentException("count 不能小于等于0");
        }
        this.threadCount = count;
    }


    public void close() {
        if (boss != null) {
            boss.shutdownGracefully();
            boss = null;
        }

        if (work != null) {
            work.shutdownGracefully();
            work = null;
        }
    }

    EventLoopGroup boss;
    EventLoopGroup work;
    ChannelFuture bootstrapFuture;

    public void start() {
        boss = new NioEventLoopGroup(1);
        work = new NioEventLoopGroup(threadCount);

        log.info(String.format("==============rpc服务启动,端口:%d 线程数: %d===========", port, threadCount));


        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boss, work)
                .channel(NioServerSocketChannel.class)//注册factory
                .childHandler(new ChannelInitializer<Channel>() {//注册piepline
                    @Override
                    protected void initChannel(Channel sc) throws Exception {//初始化连接
                        sc.pipeline()
                                // .addLast(new LoggingHandler(LogLevel.INFO))
//                                .addLast(new IdleStateHandler(0, 0, 300, TimeUnit.SECONDS))     //5分钟没有响应就关闭
//                                .addLast(new IdleHandler())
                                .addLast(new RpcServerBytesToMessageDecoder())
                                .addLast(new RpcServerMessageToBytesEncoder())
                                .addLast(new ServerHandle(serviceContainer));            //添加处理网络io类
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.TCP_NODELAY, true)//TCP无掩饰
                .childOption(ChannelOption.SO_KEEPALIVE, true);//清除死连接，维持活跃的
        bootstrapFuture = bootstrap.bind(port);
    }


    public void setPort(int port) {
        this.port = port;
    }


    public <T> void register(Class<T> type, T instance) {
        this.serviceContainer.register(type, instance);
    }
}
